﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace AMEE1
{
    class Task
    {
        /// <summary>
        /// Start und Ziel Koordinaten.
        /// </summary>
        public struct StartZiel
        {
            public Vector Start;
            public Vector Ziel;

            public StartZiel(Vector start, Vector ziel) {
                Start = start;
                Ziel = ziel;
            }
            public StartZiel(double startX, double startY, double zielX, double zielY) {
                Start = new Vector(startX, startY);
                Ziel = new Vector(zielX, zielY);
            }
        }

        public static readonly StartZiel[] TaskCoords;

        /// <summary>
        /// Anzahl Schritte bei denen vorzeitig abgebrochen wird. Standard 5000.
        /// </summary>
        public int MaxSteps = 5000;
        
        Environment _environment;
        Agent _agent;
        Random _random;

        static Task() {
            // für die punktsymmetrische Weltfunktion 2.
            // Immer gleiche Entfernung und gleiche Struktur auf direktem Wege.
            TaskCoords = new StartZiel[8];
            //TaskCoords[0] = new StartZiel(new Vector(-20.0, 20.0), new Vector(20.0, 20.0));
            //TaskCoords[1] = new StartZiel(TaskCoords[0].Ziel, TaskCoords[0].Start);
            //TaskCoords[2] = new StartZiel(new Vector(20.0, 20.0), new Vector(20.0, -20.0));
            //TaskCoords[3] = new StartZiel(TaskCoords[2].Ziel, TaskCoords[2].Start);
            //TaskCoords[4] = new StartZiel(new Vector(20.0, -20.0), new Vector(-20.0, -20.0));
            //TaskCoords[5] = new StartZiel(TaskCoords[4].Ziel, TaskCoords[4].Start);
            //TaskCoords[6] = new StartZiel(new Vector(-20.0, -20.0), new Vector(-20.0, 20.0));
            //TaskCoords[7] = new StartZiel(TaskCoords[6].Ziel, TaskCoords[6].Start);
            TaskCoords[0] = new StartZiel(new Vector(20.0, 0.0), new Vector(20.0, 20.0));
            TaskCoords[1] = new StartZiel(TaskCoords[0].Ziel, TaskCoords[0].Start);
            TaskCoords[2] = new StartZiel(new Vector(20.0, 20.0), new Vector(0.0, 20.0));
            TaskCoords[3] = new StartZiel(TaskCoords[2].Ziel, TaskCoords[2].Start);
            TaskCoords[4] = new StartZiel(new Vector(0.0, 20.0), new Vector(0.0, 0.0));
            TaskCoords[5] = new StartZiel(TaskCoords[4].Ziel, TaskCoords[4].Start);
            TaskCoords[6] = new StartZiel(new Vector(0.0, 0.0), new Vector(20.0, 0.0));
            TaskCoords[7] = new StartZiel(TaskCoords[6].Ziel, TaskCoords[6].Start);
        }

        public Task(Environment env, Agent agent) {
            _random = new Random();
            _environment = env;
            _agent = agent;
        }

        /// <summary>
        /// Startet eine Lernaufgabe mit zufälligen Start/Ziel aus <c>Task.TaskCoords</c>.
        /// </summary>
        /// <param name="stepCount">Gibt die in dieser Episode anzahl ausgeführeter Schritte zurück</param>
        /// <param name="reward">Gibt die in dieser Episode erhaltene Gesamtbelohnung zurück</param>
        public void RunTask(out int stepCount, out double reward){
            int taskNr = _random.Next(TaskCoords.Length);
            _environment.Ziel = Task.TaskCoords[taskNr].Ziel;
            _environment.ReSpawn(Task.TaskCoords[taskNr].Start.X, Task.TaskCoords[taskNr].Start.Y);
            stepCount = _agent.RunEpisode(MaxSteps);
            reward = _agent.RewardTotal;
            _agent.Reset();
        }
    }
}
